<?php

require_once PATH_FFWD.'prototypes/form.base.php';
require_once PATH_FFWD.'prototypes/field.base.php';

class BaseRecord{
	public $lasterror='';
	public $fields=Array();
	public $tablename;
	public $database='';
	private $primarykey=0;
	private $__uid=NULL;
	
	public function getTablename(){
		return $this->tablename;		
	}
	
	public function getUID(){
		
		if(!$this->__uid){			
			if((string)$this->id=='new')
				$this->__uid=uniqid();
			else
				$this->__uid=md5((string)$this->id);
		};
		return $this->__uid;		
	}
	
	public function getPointer(){
			return ''.$this->tablename.'['.$this->id.']';				
	}
	
	public function getTable(){
		$c=$this->getTableName().'Table';
		return new $c();		
	}
	
	public function reset(){
		foreach(array_keys($this->fields) as $k){
			$this->fields[$k]->value=null;			
		};
		$this->getPrimaryKey()->value='new';
	}
	
	public function &getPrimaryKey(){
		if($this->primarykey)return $this->primarykey;
		foreach($this->fields as $k=>$v){
			if($v->key){
				$this->primarykey=&$this->fields[$k];
				return $this->fields[$k];
			}
		}		
		return 0;
	}
	
	public function __construct($p=0,$f){
		$this->tablename=strtolower(substr(get_class($this),0,-6));
		eval('$this->database='.$this->tablename.'Table::$database;');
		foreach($f as $k=>$v){
			$this->fields[$k]=new DatabaseField($k,$f[$k],$this);
		};		
	}	
	
	public function fromRow($s){
		foreach($s as $k=>$v){
			if(!isset($this->fields[$k]))continue;
			$this->fields[$k]->setValue($v);		
			$this->fields[$k]->modified=0;			
		}		
	}
	
	
	
	public function saveRelatedObjects(){
		$joined_records=Array();
		foreach($this->fields as $k=>$v){			
			if(is_array($v->join)){
				$key=$v->join['table'].'.'.$v->join['column'].'.'.$v->join['local'];
				if(!isset($joined_records[$key])){
					$joined_records[$key]=Array(
						'local'=>&$this->fields[$v->join['local']],
					);
				}
				$joined_records[$key][]=$v;								
			}			
		}			
		foreach($joined_records as $joined_record){
			if($joined_record['local']->value=='new'){
				$tbl_name=$joined_record[0]->join['table'];
				$tbl=$tbl_name.'Table';
				$tbl=new $tbl();
				$rec=$tbl->getById('new'); 
				foreach($joined_record as $k=>$v){
					if($k==='local')continue;
					if(!preg_match('/`'.$tbl_name.'`.`([a-zA-Z0-9\_]*)`/',$v->query,$o))continue;
					$o=$o[1];
					$rec->$o=$v->value;				
				}				
				$rec->save();
				$joined_record['local']->value=$rec->pk;				
			}			
		}
	}
	
	public function save(){
		//TODO: implement joined record save!
		//if($this->lasterror)return 1;
		$pk=$this->getPrimaryKey()->name;
		if(!$this->fields[$pk]->value){
			throw new Exception('Entity not initalized');
		}
		try{
			$this->saveRelatedObjects();
		}catch(Exception $e){
			//cannot save related record..			
		}
		
		
		$onlyonfirstsave=Array('created_at','created_by','added_at','added_by');
		$new=($this->fields[$pk]->value=='new');
		if( $new && isset($this->fields['created_at']))$this->fields['created_at']->value='now()';
		if( $new && isset($this->fields['added_at']))$this->fields['added_at']->value='now()';
		if(!$new && isset($this->fields['updated_at']))$this->fields['updated_at']->value='now()';
		if(!$new && isset($this->fields['modified_at']))$this->fields['modified_at']->value='now()';
		if($GLOBALS['user']->name){
			if( $new && isset($this->fields['created_by']))$this->fields['created_by']->value=$GLOBALS['user']->id;
			if( $new && isset($this->fields['added_by']))$this->fields['added_by']->value=$GLOBALS['user']->id;
			if( $new && isset($this->fields['user_id']) && !$this->fields['user_id']->value)$this->fields['added_by']->value=$GLOBALS['user']->id;			
			if(!$new && isset($this->fields['updated_by']))$this->fields['updated_by']->value=$GLOBALS['user']->id;
			if(!$new && isset($this->fields['modified_by']))$this->fields['modified_by']->value=$GLOBALS['user']->id;			
		}
		if(isset($this->fields['modified_at']))$this->fields['modified_at']->value='now()';
		if(isset($GLOBALS['user'])){
			if($new && isset($this->fields['created_by']))$this->fields['created_by']->value=(string)$GLOBALS['user']->id;
			if(isset($this->fields['modified_by']))$this->fields['modified_by']->value=(string)$GLOBALS['user']->id;			
		}
		if($new)
			$q='INSERT INTO `'.$this->tablename.'` SET ';
		else
			$q='UPDATE `'.$this->tablename.'` SET ';
		foreach($this->fields as $k=>$v){
			if(!$new && in_array($k,$onlyonfirstsave))continue;
			if($v->unique){
				if(!$v->isUnique())throw new Exception('Field value is not unique: '.$k.'='.$v->value);				
			}
			if($k==$pk || $this->fields[$k]->nq==-1)continue;
			$nq=$this->fields[$k]->nq;
			if(!$v->value && $v->type!='varchar' && $v->type!='text' && $v->type!='int' && $v->type!='tinyint'){
				$v->value='NULL';$nq=0;			
			};
			if($v->type=='timestamp'){
				$this->fields[$k]->value=strdatetime2timestamp($this->fields[$k]->__toString());
			}
			
			if($v->type=='int'){
				if(!$this->fields[$k]->value){
					if(0 && $this->fields[$k]->NULL){//ne állítsa NULL-ra a '0' INT mezőket
						$this->fields[$k]->value='NULL';
					}else{
						$this->fields[$k]->value=(int)$v->value;				
					}
				};
			}
			if($v->type=='float')$this->fields[$k]->value=(float)$v->value;
			if($v->type=='boolean' && $v->value=='NULL')$v->value='0';
			if($v->value=='NULL')$nq=0;
			
			if($v->nq)$val=$GLOBALS['db']->escape_string($v->value);else $val=$v->value;
			if($v->type=='timestamp' && $val!='NULL'){$val='FROM_UNIXTIME('.$val.')';$nq=0;};
			
			if($val=='now()')$nq=0;
			
			$q.='`'.$k.'`='.($nq?"'":'').$val.($nq?"', ":', ');
		};
		$q=substr($q,0,-2).' ';
		if(!$new)$q.="WHERE `$pk`=".$this->fields[$pk]->value;
		$tn=$this->tablename.'Table';
		console_log('saveQuery:'.$q);
		$GLOBALS[$this->database]->query($q.';');
		
		if($new){
			$this->fields['id']->value=$GLOBALS[$this->database]->insert_id();
		}
	}
	
	public function __get($k){
		if($k=='pk')$k=$this->getPrimaryKey()->name;
		if(!isset($this->fields[$k]))return 0;
		return $this->fields[$k];		
	}
	
	public function __set($k,$v){
		if(!isset($this->fields[$k])){$this->lasterror='field_doesnt_exist';return 0;};
		$f=&$this->fields[$k];
		//if($f->nq==-1){$this->lasterror='field_is_foreign';return 0;};
		if($k=='id' && $v=='new')
			$err=0;
		else 
			$err=$f->validate_value($v);
		if($err){
				$this->lasterror=$err;
				return 1;
		};		
		$f->setValue($v);	
		$f->modified=1;	
		return 0;
	}
	
	public function delete(){
		if($this->id && $this->id!='new'){			
			$q="DELETE FROM `".$this->tablename."` WHERE `id`=".$this->id.";";
			$GLOBALS[$this->database]->query($q);			
		}		
	}
	
	public function dump(){
		if(CLI){
			$arr=Array();
			foreach($this->fields as $k=>$v){
				$arr[]=Array($k,$v);
			}
			print_cli_2d($arr);
		}else{		
			echo "<table border='1'><tbody valign='top'>";
			foreach($this->fields as $k=>$v){
				echo "<tr><td>".$k.":</td><td>".$this->fields[$k]->value."</td></tr>";			
			};
			echo "</tbody></table>";
		};
	}
	
	public function toArray(){
		$r=Array();
		foreach($this->fields as $k=>$v){
			$r[$k]=$v->value;
		}
		return $r;
	}
	
	public function getChildren(){
		if(!isset($this->fields['parent_id']))
			throw new Exception('Method cannot be called on table does not have PARENT_ID field');
		$t=$this->getTable();
		
		return $t->getAll(Array(
			'parent_id'=>(string)$this->getPrimaryKey()
		));
	}
	
}



?>
